/*
 * nrf24l01.c
 *
 *  Created on: Oct 16, 2013
 *      Author: IEUser
 */


/******************************************************************************************
 *	Deklaracje dołączanych plików nagłówkowych i bibliotek								 *
 *****************************************************************************************/
#include <avr/io.h>
#include <util/delay.h>

#include "nrf24l01.h"

/******************************************************************************************
 *	Deklaracje zmiennych globalnych								                         *
 *****************************************************************************************/

/******************************************************************************************
 *	Deklaracje funkcji															 		 *
 *****************************************************************************************/

/*
 * 	Funkcja inicjalizujaca trasceiver nRF24L01
 */
void nrf24l01_init(void){
	spi_init(); //inicjalizacja sprzetowego interfejsu SPI

	NRF24L01_DDR |= (1<<NRF24L01_CE) | (1<<NRF24L01_CSN); //CE i CSN jako wyjscia
    NRF24L01_PORT |= (1<<NRF24L01_CSN);	//CSN w stan wysoki
    NRF24L01_PORT &= ~(1<<NRF24L01_CE);	//CE w stan niski
}/* nrf24l01_init */

/*
 * 	Funkcja konfigurujaca tryb pracy nRF24L01
 * 	Argument:	mode - tryb pracy {RX_MODE, TX_MODE, STANDBY_MODE}
 */
void nrf24l01_config(uint8_t mode){
	nrf24l01_write_register(RF_CH, CHANNEL);	//wybor kanalu radiowego (0...127)

	nrf24l01_write_register(RX_PW_P0, PAYLOAD);	//wybor dlugosci pola PAYLOAD na pipe P0
	nrf24l01_write_register(RX_PW_P1, PAYLOAD);	//wybor dlugosci pola PAYLOAD na pipe P1

	nrf24l01_write_register(RF_SETUP, (RF_PWR_0<<RF_PWR_MASK) | (LNA_HCURR_1<<LNA_HCURR_MASK) | (RF_DR_2M<<RF_DR_MASK)); //konfiguracja parametrow nadawczych

	if(mode ==  TX_MODE){
		nrf24l01_write_register(CONFIG, (0<<PRIM_RX)|(1<<PWR_UP)|(1<<EN_CRC)); //tryb TX, STANDBY mode
		nrf24l01_flush_fifo(TX_MODE); //wyczysc rejestry nadawcze
	}else if(mode == RX_MODE){
		nrf24l01_write_register(CONFIG, (1<<PRIM_RX)|(1<<PWR_UP)|(1<<EN_CRC)); //tryb RX, STANDBY mode
		NRF24L01_CE_HIGH; //tryb RX
		_delay_us(150); //odczekaj na uruchomienie odbiornika
		nrf24l01_write_register(STATUS, (1<<TX_DS)|(1<<MAX_RT)); //skasowanie flag TX_DS oraz MAX_RT
		nrf24l01_flush_fifo(RX_MODE); //wyczysc rejestry odbiorcze
	}else{
		nrf24l01_write_register(CONFIG, (0<<PRIM_RX)|(0<<PWR_UP)|(1<<EN_CRC)); //tryb TX, POWER DOWN mode
	}
}/* nrf24l01_config */

/*
 * 	Funkcja czyszczaca rejestry nadawczo-odbiorcze nRF24L01
 * 	Argument:	mode - rejestry na podstawie trybu pracy {RX_MODE, TX_MODE}
 */
void nrf24l01_flush_fifo(uint8_t mode){
	NRF24L01_CSN_LOW;

	if(mode == TX_MODE)
		spi_write_byte(FLUSH_TX); //wyczysc rejestry nadawcze
	else
		spi_write_byte(FLUSH_RX); //wyczysc rejestry odbiorcze

	NRF24L01_CSN_HIGH;
}/* nrf24l01_flush_fifo */

uint8_t nrf24l01_data_ready(void){
	uint8_t status;

	nrf24l01_read_register(STATUS, &status, 1);

	if(status & (1<<RX_DR))
		return 1;
	else{
		nrf24l01_read_register(FIFO_STATUS, &status, 1);
		return (status & (1<<RX_EMPTY));
	}

}

/*
 * 	Funkcja pobierajaca dane z rejestrow odbiorczych nRF24L01
 * 	Argument:	*data - wskaznik na tablice do ktorej maja zostac zapisane odebrane dane
 */
void nrf24l01_get_data(char *data){
	uint8_t i, status;

	NRF24L01_CSN_LOW;

	spi_write_byte(R_RX_PAYLOAD); //wyslanie komendy rozpoczynajacej odbior danych z buforow odbiorczych

	for(i=0; i<PAYLOAD; i++){
		*data++ = spi_read_byte(); //zapis danych do kolejnych elementow tablicy
	}

	NRF24L01_CSN_HIGH;

	nrf24l01_flush_fifo(RX_MODE); //wyczysc rejestry odbiorcze

	nrf24l01_read_register(STATUS, &status, 1); //odczyt rejestru statusowego
	status |= (1<<RX_DR); //skasowanie flagi RX_DR - odebrane dane
	nrf24l01_write_register(STATUS, status); //zapis rejestru statusowego
}/* nrf24l01_get_data */

void nrf24l01_send(char *data){
	uint8_t i;

	NRF24L01_CE_LOW; //wyjscie z trybu odbiorczego (jesli byl ustawiony)

	nrf24l01_config(TX_MODE); //konfiguracja jako nadajnik

	NRF24L01_CSN_LOW;

	spi_write_byte(W_TX_PAYLOAD | 0x20); //wyslanie komendy rozpoczynajacej przeslanie danych do buforow nadawczych
	for(i=0; i<PAYLOAD; i++){
		spi_write_byte(*data++); //wysylanie kolejnych elementow tablicy
	}

	NRF24L01_CSN_HIGH;

	NRF24L01_CE_HIGH; //stan wysoki na linii CE
	_delay_us(20);
	NRF24L01_CE_LOW; //stan niski na linii CE - wyslanie danych z buforow nadawczych
}/* nrf24l01_send */

/*
 * 	Funkcja odczytu bajtu z rejestru nRF24L01
 * 	Argument: reg - rejestr odczytu,
 * 			  *data - wskaznik na tablice w ktorej ma zostac zapisany wynik odczytu,
 * 			  lenght - ilosc bajtow do odczytania z rejestru
 */
void nrf24l01_read_register(uint8_t reg, uint8_t *data, uint8_t lenght){
	uint8_t i;

	NRF24L01_CSN_LOW;

	spi_write_byte(0x1F & reg); //wyslanie adresu rejestru do oczytu

	for(i=0; i<lenght; i++){
		*data++ = spi_read_byte();
	}

	NRF24L01_CSN_HIGH;
}/* nrf24l01_read_register */

/*
 * 	Funkcja zapisu bajtu do rejestru nRF24L01
 * 	Argument: reg - rejestr zapisu,
 * 			  byte - bajt danych do zapisu
 */
void nrf24l01_write_register(uint8_t reg, uint8_t byte){
	NRF24L01_CSN_LOW;

	spi_write_byte(reg | 0x20); //wyslanie adresu rejestru do zapisu
	spi_write_byte(byte); //wyslanie bajtu danych do rejestru

	NRF24L01_CSN_HIGH;
}/* nrf24l01_write_register */


/******************************************************************************************
 *	Koniec pliku nrf24l01.c
 *****************************************************************************************/
